package com.neu.utils;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class LuaScriptService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 存储 Lua 脚本的缓存
    private ConcurrentHashMap<String, DefaultRedisScript<Object>> scriptCache = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() throws IOException {
        // 预加载一些常用的 Lua 脚本
        //loadScript("lua/unlock.lua");
        //loadScript("lua/kill.lua");
        // 可以在这里预加载多个脚本
    }

    /**
     * 加载 Lua 脚本到内存缓存
     * @param scriptFilePath
     * @throws IOException
     */
    public void loadScript(String scriptFilePath) throws IOException {
        //这个方法通过 Spring 的资源加载机制，可以直接读取 resources 目录下的 Lua 脚本文件，并将其传递给 DefaultRedisScript 对象。
        //Spring 提供的 ClassPathResource 和 ResourceScriptSource 能够帮助你更方便地加载资源，避免了文件读取过程中的细节处理。
        ClassPathResource resource = new ClassPathResource(scriptFilePath);
        //String scriptContent = new String(Files.readAllBytes(Paths.get(resource.getURI())));
        String scriptContent ;
        try (InputStream inputStream = resource.getInputStream();
             InputStreamReader reader = new InputStreamReader(inputStream);
             BufferedReader bufferedReader = new BufferedReader(reader)) {
            StringBuilder scriptContent1 = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                scriptContent1.append(line).append("\n");
            }
            scriptContent = scriptContent1.toString();
        }
        DefaultRedisScript<Object> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(scriptContent);
        redisScript.setResultType(Object.class);

        scriptCache.put(scriptFilePath, redisScript);
    }

    /**
     * 执行 Lua 脚本
     *
     * @param scriptFilePath Lua 脚本文件路径 例如lua/tokenCheck.lua
     * @param returnType 脚本返回类型
     * @param keys 脚本需要的键
     * @param args 脚本参数
     * @param <T> 返回值类型
     * @return 执行结果
     */
    public <T> T executeLuaScriptFromFile(String scriptFilePath, Class<T> returnType, List<String> keys, Object... args) {
        // 创建 Redis 脚本对象，指定返回值类型
        DefaultRedisScript<T> redisScript = (DefaultRedisScript<T>) scriptCache.get(scriptFilePath);
        if (redisScript == null) {
            throw new IllegalArgumentException("脚本未缓存: " + scriptFilePath);
        }

        // 设置返回值类型
        redisScript.setResultType(returnType);

        // 执行脚本并返回结果
        return redisTemplate.execute(redisScript, keys, args);

    }

}
